package me.fung.wubi.worker.builder

import kotlinx.coroutines.*
import me.fung.wubi.base.define.action.ProcessAction
import me.fung.wubi.base.define.table.CodeTable
import me.fung.wubi.base.define.table.Lexicon
import me.fung.wubi.base.define.value.WordFrequency
import java.io.File

object FileResourcesLoader {

    /**
     * 读取字典
     */
    fun loadLexicon(files: List<File>): Lexicon = Lexicon().apply {
        files.filter { it.exists() }.forEach {
            loadFromFile(it)
        }
    }

    fun loadWordFrequency(files: List<File>): WordFrequency = WordFrequency().apply {
        files.filter { it.exists() }.forEach {
            loadFromFile(it)
        }
    }

    /**
     * 读取词组
     */
    suspend fun loadGroup(lexicon: Lexicon, files: List<File>): List<CodeTable> = coroutineScope {
        val list = ArrayList<CodeTable>()
        files.filter { it.exists() }.forEach { file ->
            launch {
                val table = CodeTable(lexicon, file)
                synchronized(list) {
                    list.add(table)
                }
            }
        }
        list
    }

    /**
     * 读取简码
     */
    suspend fun loadShort(files: List<File>, action: ProcessAction): List<CodeTable> = coroutineScope {
        val list = ArrayList<CodeTable>()
        files.filter { it.exists() }.forEach { file ->
            launch {
                val table = CodeTable(file, action = action)
                synchronized(list) { list.add(table) }
            }
        }
        list
    }

    /**
     * 读取生僻字
     */
    suspend fun loadRare(lexicon: Lexicon, files: List<File>, action: ProcessAction): List<CodeTable> = coroutineScope {
        val list = ArrayList<CodeTable>()
        files.filter { it.exists() }.forEach { file ->
            val table = CodeTable(lexicon, wordFile = file, action = action)
            synchronized(list) {
                list.add(table)
            }
        }
        list
    }

    fun load(resources: FileResources): FileResources.Content = runBlocking(Dispatchers.IO) {
        // 字典
        val lexiconDeferred = async { loadLexicon(resources.lexiconFiles) }
        // 词频文件
        val wordFrequencyDeferred = async { loadWordFrequency(resources.wordFrequencyFiles) }
        val wordFrequency = wordFrequencyDeferred.await()
        val lexicon = lexiconDeferred.await()
        // 词组
        val groupDeferred = async { loadGroup(lexicon, resources.groupFiles) }
        // 普通码
        val simpleTable = async { CodeTable(lexicon) }.await()
        val removeBlock: ProcessAction = { code, word -> simpleTable.remove(code, word) }
        // 简码
        val shortFullCodeTable = CodeTable()
        val short = async {
            loadShort(resources.shortCodeFiles) { _, word ->
                val fullCode = lexicon.codeOfWord(word)
                removeBlock(fullCode, word)
                shortFullCodeTable.add(fullCode, word)
            }
        }
        // 生僻字
        val rareDeferred = async { loadRare(lexicon, resources.rareFiles, removeBlock) }

        val groupList = groupDeferred.await()
        val shortList = short.await()
        val rareList = rareDeferred.await()
        FileResources.Content(
            lexicon = lexicon,
            wordFrequency = wordFrequency,
            shortCodeTables = shortList,
            shortFullCodeTable = shortFullCodeTable,
            rareTables = rareList,
            groupTables = groupList,
            simpleTable = simpleTable,
        )
    }
}